package handler

import (
	"bytes"
	"context"
	"encoding/json"
	"errors"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/status"
	"gorm.io/gorm"
	"io"
	"net/http"
	"service_base_shop/user_srv/global"
	"service_base_shop/user_srv/model"
	"service_base_shop/user_srv/proto"
	"service_base_shop/user_srv/utils"
	"strings"
	"time"
)

type User struct {
}

//获取openid
func (this *User) GetOpenId(ctx context.Context, GetOpenIdReq *protopb.GetOpenIdReq) (*protopb.GetOpenIdRep, error) {
	appid := global.WeixinConfig.Appid
	secret := global.WeixinConfig.Secret
	get_token_url := "https://api.weixin.qq.com/sns/jscode2session?appid=" + appid + "&secret=" + secret + "&js_code=" + GetOpenIdReq.Code + "&grant_type=authorization_code"
	rep, err := http.Get(get_token_url)
	if err != nil {
		return nil, status.Error(codes.NotFound, "服务发生失败")
	}
	defer rep.Body.Close()
	var buffer [512]byte
	result := bytes.NewBuffer(nil)
	for {
		n, err := rep.Body.Read(buffer[0:])
		result.Write(buffer[0:n])
		if err != nil && err == io.EOF {
			break
		} else if err != nil {
			return nil, status.Error(codes.NotFound, "服务发生失败")
		}
	}
	login := model.Login{}
	json.Unmarshal(result.Bytes(), &login)
	if login.ErrCode != "" {
		return nil, status.Error(codes.NotFound, "获取失败")
	}
	return &protopb.GetOpenIdRep{
		Status:     1,
		Openid:     login.OpenId,
		SessionKey: login.SessionKey,
	}, nil
}

//登录或者注册
func (this *User) AuthLogin(ctx context.Context, AuthLoginReq *protopb.AuthLoginReq) (*protopb.AuthLoginRep, error) {

	User := model.User{}
	AuthLoginRep := protopb.AuthLoginRep{}
	if err := global.DB.Table("lr_user").Where("openid = ?",AuthLoginReq.Openid).Take(&User).Error; err != nil {
		if !errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, status.Errorf(codes.NotFound,"服务内部错误")
		}
		//新增
		User.Name = AuthLoginReq.NickName
		User.Uname = AuthLoginReq.NickName
		User.Sex = int(AuthLoginReq.Gender)
		User.Openid = AuthLoginReq.Openid
		User.Photo = AuthLoginReq.HeadUrl
		User.Addtime = time.Now().Unix()
		User.Source = "wx"
		if err = global.DB.Table("lr_user").Create(&User).Error; err != nil {
			return nil, status.Errorf(codes.NotFound,"新增失败")
		}
		AuthLoginRep.ID = User.Id
		AuthLoginRep.HeadUrl = User.Photo
		AuthLoginRep.NickName = User.Name
	}else {
		if User.Del != 0 {
			return nil, status.Errorf(codes.NotFound,"账号已被禁用")
		}
		User.Name = AuthLoginReq.NickName
		User.Uname = AuthLoginReq.NickName
		User.Sex = int(AuthLoginReq.Gender)
		User.Openid = AuthLoginReq.Openid
		User.Photo = AuthLoginReq.HeadUrl

		if err := global.DB.Table("lr_user").Where("id = ?",User.Id).Updates(&User).Error; err != nil{
			return nil, status.Errorf(codes.NotFound,"更新失败")
		}

		AuthLoginRep.ID = User.Id
		AuthLoginRep.HeadUrl = User.Photo
		AuthLoginRep.NickName = User.Name
	}
	return &AuthLoginRep, nil
}


//加入购物车

func (this *User) AddChrt(ctx context.Context, req *protopb.AddChrtReq) (*protopb.AddChrtRep, error) {
	user_id := req.Id
	pid := req.Pid
	num := req.Num
	check_info,ok := check_cart(pid)
	if !ok {
		return nil, status.Errorf(codes.NotFound,"商品不存在或已经下价")
	}
	//判断库存
	if check_info.Num <= int(num) {
		return nil, status.Errorf(codes.NotFound,"库存不足!")
	}
	//判断购物车内是否已经存在该商品

	cart_info := model.ShoppingChar{}
	is_cart := true
	if err := global.DB.Table("lr_shopping_char").
		Where("pid = ? and uid = ?",pid,user_id).
		Select("*").Take(&cart_info).Error; err != nil{
		if errors.Is(err,gorm.ErrRecordNotFound) {
			is_cart = false
		}else {
			return nil, status.Errorf(codes.NotFound,"购物车查询错误!")
		}
	}
	if is_cart {
		cart_info.Num += int(num)
		if check_info.Num <= cart_info.Num  {
			return nil, status.Errorf(codes.NotFound,"库存不足!")
		}
		if err := global.DB.Table("lr_shopping_char").Where("id = ?",cart_info.Id).Update("num",cart_info.Num).Error; err != nil {
			return nil, status.Errorf(codes.NotFound,"购物车更新失败!")
		}
	}else {
		cart_info.Num = int(num)
		cart_info.Addtime = time.Now().Unix()
		cart_info.Pid = pid
		cart_info.Uid = user_id
		cart_info.ShopId = check_info.ShopId
		cart_info.Price = check_info.PriceYh
		if check_info.ProType > 0 {
			cart_info.Type = check_info.ProType
		}else {
			cart_info.Type = 1
		}
		if err := global.DB.Table("lr_shopping_char").Create(&cart_info).Error; err != nil{
			return nil, status.Errorf(codes.NotFound,"加入购物车失败")
		}
	}
	return &protopb.AddChrtRep{CartId: cart_info.Id}, nil
}

//购物车列表
func (this *User) ChrtList (ctx context.Context, req *protopb.ChrtListReq) (*protopb.ChrtListRep,error)  {

	list := []*protopb.ChrtInfo{}
	//name,photo_x
	if err := global.DB.Table("lr_shopping_char as c").
		Joins("left join lr_product as p on p.id = c.pid").
		Where("c.uid = ?",req.UserId).
		Select("c.id,c.uid,c.pid,c.price,c.num,p.name as pro_name,p.photo_x").
		Find(&list).Error; err != nil{
		if errors.Is(err,gorm.ErrRecordNotFound) {
			return &protopb.ChrtListRep{List: list},nil
		}else {
			return nil,status.Errorf(codes.NotFound,"查询错误")
		}
	}
	if len(list)  > 0 {
		for _,v := range list {
			v.PhotoX = global.DataUrl + v.PhotoX
		}
	}
	return &protopb.ChrtListRep{List: list},nil
}

//删除
func (this *User) DelCart (ctx context.Context, req *protopb.DelCartReq) (*protopb.Empty,error)  {
	cart := model.ShoppingChar{}
	if err := global.DB.Table("lr_shopping_char").Where("id = ? and uid = ?",req.CartId,req.UserId).Take(&cart).Error; err != nil{
		if errors.Is(err,gorm.ErrRecordNotFound) {
			return nil,status.Errorf(codes.NotFound,"非法请求")
		}else {
			return nil,status.Errorf(codes.NotFound,"查询失败了")
		}
	}
	del_cart := model.ShoppingChar{
		Id: cart.Id,
	}
	if err := global.DB.Table("lr_shopping_char").Delete(&del_cart).Error; err != nil{
		return nil,status.Errorf(codes.NotFound,"移除失败了")
	}
	return &protopb.Empty{},nil
}


//删除多个
func (this *User) DelCatMany (ctx context.Context, req *protopb.DelCatManyReq) (*protopb.Empty,error)  {
	global.DB.Begin()
	for _,v := range req.CartId{
		cart := model.ShoppingChar{}
		if err := global.DB.Table("lr_shopping_char").Where("id = ? and uid = ?",v,req.UserId).Take(&cart).Error; err != nil{
			global.DB.Rollback()
			if errors.Is(err,gorm.ErrRecordNotFound) {
				return nil,status.Errorf(codes.NotFound,"非法请求")
			}else {
				return nil,status.Errorf(codes.NotFound,"查询失败了")
			}
		}
		del_cart := model.ShoppingChar{
			Id: cart.Id,
		}
		if err := global.DB.Table("lr_shopping_char").Delete(&del_cart).Error; err != nil{
			global.DB.Rollback()
			return nil,status.Errorf(codes.NotFound,"移除失败了")
		}
	}
	global.DB.Commit()
	return &protopb.Empty{},nil
}


//***************************
//  会员立即购买下单接口
//***************************

//更新
func (this *User) UpdataCart (ctx context.Context, req *protopb.UpdataCartReq) (*protopb.Empty,error)  {
	cart := model.ShoppingChar{}
	if err := global.DB.Table("lr_shopping_char").Where("id = ? and uid = ?",req.CartId,req.UserId).Take(&cart).Error; err != nil{
		if errors.Is(err,gorm.ErrRecordNotFound) {
			return nil,status.Errorf(codes.NotFound,"非法请求")
		}else {
			return nil,status.Errorf(codes.NotFound,"查询失败了")
		}
	}

	check_info,ok := check_cart(cart.Pid)
	if !ok {
		return nil, status.Errorf(codes.NotFound,"商品不存在或已经下价")
	}
	//判断库存
	if check_info.Num <= int(req.Num) {
		return nil, status.Errorf(codes.NotFound,"库存不足!")
	}
	cart.Num = int(req.Num)

	if err := global.DB.Table("lr_shopping_char").Where("id = ?",cart.Id).Update("num",cart.Num).Error; err != nil {
		return nil, status.Errorf(codes.NotFound,"购物车更新失败!")
	}
	return &protopb.Empty{},nil
}


//***************************
//  会员商品收藏接口
//***************************
func (this *User) CollGoods(ctx context.Context, req *protopb.CollGoodsReq) (*protopb.Empty,error) {
	product_sc := model.ProductSc{}
	is_check := true
	if err := global.DB.Table("lr_product_sc").Where("uid = ? and pid = ?",req.UserId,req.Pid).Select("id").Take(&product_sc).Error; err != nil{
		if errors.Is(err,gorm.ErrRecordNotFound) {
			is_check = false
		}else {
			return nil,status.Errorf(codes.NotFound,"查询失败了")
		}
	}
	if is_check {
		if err := global.DB.Table("lr_product_sc").Delete(&product_sc).Error; err != nil{
			return nil,status.Errorf(codes.NotFound,"移除失败了")
		}
	}else {
		product_sc.Pid = req.Pid
		product_sc.Uid = req.UserId
		if err := global.DB.Table("lr_product_sc").Create(&product_sc).Error; err != nil{
			return nil, status.Errorf(codes.NotFound,"收藏失败失败")
		}
	}
	return &protopb.Empty{},nil
}

//获取优惠券
func (this *User) GetVoucher(ctx context.Context, req *protopb.GetVoucherReq) (*protopb.GetVoucherRep,error) {
	vou_list := []*model.UserVoucher{}
	global.DB.Table("lr_user_voucher").Where("uid = ? and status != 2",req.UserId).Find(&vou_list)
	offdates := []*protopb.Voucher{}
	nouses := []*protopb.Voucher{}
	userds := []*protopb.Voucher{}
	for _,v := range vou_list {
		vou_info := model.Voucher{}
		global.DB.Table("lr_voucher").Where("id = ?",v.Vid).Take(&vou_info)
		if vou_info.Del == 1 || vou_info.EndTime < time.Now().Unix() {
			offdate := &protopb.Voucher{}
			offdate.Vid = vou_info.Id
			offdate.FullMoney = vou_info.FullMoney
			offdate.Amount = vou_info.Amount
			offdate.StartTime = utils.Int64ToTime(vou_info.StartTime)
			offdate.EndTime = utils.Int64ToTime(vou_info.EndTime)
			offdates = append(offdates,offdate)
		}else if  vou_info.EndTime > time.Now().Unix() {
			nouse := &protopb.Voucher{}
			nouse.Vid = vou_info.Id
			nouse.ShopId = vou_info.ShopId
			nouse.Title = vou_info.Title
			nouse.FullMoney = vou_info.FullMoney
			nouse.Amount = vou_info.Amount
			if vou_info.Proid == "all" || vou_info.Proid == "" {
				nouse.Desc = "店内通用"
			}else {
				nouse.Desc = "限定商品"
			}
			nouse.StartTime = utils.Int64ToTime(vou_info.StartTime)
			nouse.EndTime = utils.Int64ToTime(vou_info.EndTime)
			if vou_info.Proid != ""{
				proid := strings.Split(vou_info.Proid,",")
				nouse.Proid = proid[0]
			}
			nouses = append(nouses,nouse)
		}
	}
	vouusedlist :=  []*model.UserVoucher{}
		global.DB.Table("lr_user_voucher").Where("uid = ? and status = 2",req.UserId).Find(&vou_list)

	for _,v := range vouusedlist {
		vou_info := model.Voucher{}
		global.DB.Table("lr_voucher").Where("id = ?",v.Vid).Take(&vou_info)
		userd := &protopb.Voucher{}
		userd.Vid = vou_info.Id
		userd.FullMoney = vou_info.FullMoney
		userd.Amount = vou_info.Amount
		userd.StartTime = utils.Int64ToTime(vou_info.StartTime)
		userd.EndTime = utils.Int64ToTime(vou_info.EndTime)
		userds = append(userds,userd)
	}

	return &protopb.GetVoucherRep{Nouses: nouses,Offdates: offdates,Useds: userds},nil

}


//购物车添加。删除检测公共方法
func check_cart(pid int64) (*model.Product , bool) {
	product := model.Product{}
	if err := global.DB.Table("lr_product").Where("id = ? and del = 0 and is_down = 0",pid).Take(&product).Error; err != nil{
		if errors.Is(err,gorm.ErrRecordNotFound) {
			return nil,false
		}else {
			return nil,false
		}
	}
	return &product,true

}





